<script lang="ts" setup>
import QuestionPanel from "./components/question-panel.vue";
import BottomBar from "./components/bottom-bar.vue";
import NumList from "./components/num-list.vue";
import { usePracticeStore } from "@/store/modules/practice";
import * as questionApi from "@/api/train/question";
import { PracticeMode, Question, QuestionState, QuestionOptionIndex, UpdateActionRecordParams } from "@/types/practice";

interface IProps {
  practiceMode: PracticeMode;
  questionIds: Question["id"][];
  questionsMap: Map<Question["id"], Question>;
  questionsStateMap: Map<string, QuestionState>;
  questionChoosedAnswerMap: Map<Question["id"], QuestionOptionIndex[]>;
  correctCount: number;
  wrongCount: number;
  uniqueFlag?: string;
  showSubmit?: boolean;
}

const props = withDefaults(defineProps<IProps>(), {
  loadActionRecord: false,
  showSubmit: false,
});

const practiceStore = usePracticeStore();

const emit = defineEmits<{
  (e: "chooseAnswer", questionId: Question["id"], optionIndexList: QuestionOptionIndex[], isCorrect: boolean): void;
  (e: "updateCollectRecord", questionId: Question["id"], isCollect: boolean): void;
  (e: "updateActionRecord", params: UpdateActionRecordParams): void;
  (e: "update:questionsMap", value: Map<Question["id"], Question>): void;
  (e: "end"): void;
  (e: "submit"): void;
}>();

// 加载题目id列表
const loadQuestionsByIds = async (ids: Question["id"][]) => {
  if (!ids.length) return;

  const res = await questionApi.listQuestionByIds(ids);
  const questionsMap = res.data.reduce((prev, cur) => prev.set(cur.id, cur), new Map<Question["id"], Question>(props.questionsMap));
  emit("update:questionsMap", questionsMap);
};

// 选择答案
const handleChooseAnswer = (questionId: Question["id"], optionIndexList: QuestionOptionIndex[], isCorrect: boolean) =>
  emit("chooseAnswer", questionId, optionIndexList, isCorrect);

const handleUpdateActionRecord = (params: UpdateActionRecordParams) => emit("updateActionRecord", params);

// 当前做题的下标，以及持久化
const currentIndex = props.uniqueFlag
  ? computed({
      get: () => practiceStore.indexHistory[props.uniqueFlag!] || 0,
      set: (value) => practiceStore.updateIndexHistory(props.uniqueFlag!, value),
    })
  : ref(0);

// 下标变化自动加载附近题目
watch(currentIndex, (index) => {
  // 检查是否需要加载
  const checkMin = Math.max(0, index - 10);
  const checkMax = Math.min(props.questionIds.length, index + 10);
  // 检查范围内是否有未加载题目，有则加载
  const needLoad = props.questionIds.slice(checkMin, checkMax).some((id) => !props.questionsMap.has(id));

  if (needLoad) {
    const loadMin = Math.max(0, index - 20);
    const loadMax = Math.min(props.questionIds.length, index + 20);
    const notLoadIds = props.questionIds.slice(loadMin, loadMax).filter((id) => !props.questionsMap.has(id));
    notLoadIds.length && loadQuestionsByIds(notLoadIds);
  }
});

const goto = (index: number) => (currentIndex.value = index);
defineExpose({
  goto,
});

watch(
  () => props.questionIds,
  async () => {
    // 加载前20道题目
    const startIndex = Math.max(0, currentIndex.value - 20);
    const endIndex = Math.min(props.questionIds.length, currentIndex.value + 20);
    const ids = props.questionIds.slice(startIndex, endIndex);
    await loadQuestionsByIds(ids);
  }
);

// 题号列表是否可见
const numListVisible = ref<boolean>(false);
</script>

<template>
  <QuestionPanel
    class="basis-0 grow relative of-hidden"
    :mode="practiceMode"
    :question-ids="questionIds"
    :questions-state-map="questionsStateMap"
    :question-choosed-answer-map="questionChoosedAnswerMap"
    v-model:current-index="currentIndex"
    @end="$emit('end')"
    @choose-answer="handleChooseAnswer"
    @update-action-record="handleUpdateActionRecord"
  />
  <BottomBar
    class="h-14 shrink-0 bg-white b-t-1.5 b-t-solid b-t-gray-2"
    :total="questionIds.length"
    :correct-count="correctCount"
    :wrong-count="wrongCount"
    :question-ids="questionIds"
    :questions-state-map="questionsStateMap"
    :current-index="currentIndex"
    :show-submit="showSubmit"
    @on-show-num-list="numListVisible = true"
    @submit="$emit('submit')"
    @update-collect-record="(...args) => $emit('updateCollectRecord', ...args)"
  />
  <NumList
    v-model:visible="numListVisible"
    v-model:current-index="currentIndex"
    :question-ids="questionIds"
    :questions-state-map="questionsStateMap"
  />
</template>
